#include "common.h"
#include "msn_soap2.h"

/* for sso */
static GString * sso_soap_xml_gen(const char *name, const char *pass);
static void rst_node_gen(xmlNodePtr par, int id, char *addr, char *uri);

GString *msn_soap_gen(const char *host, const char *url, const char *soapaction, GString *xml)
{
	GString *res = NULL;

	g_assert(host && url && soapaction && xml);
	res = g_string_new(NULL);
	g_string_printf(res, "POST %s HTTP/1.1\r\n"
					     "Host: %s\r\n"
						 "SOAPAction: %s\r\n"
						 "Content-Type: text/xml; charset=utf-8\r\n"
						 "Content-Length: %d\r\n\r\n", url, host, soapaction, xml->len);
	g_string_append_len(res, xml->str, xml->len);
	debug_log(9, "SOAP %d bytes {%s}\n", res->len, res->str);
	g_string_free(xml, 1);
	return res;
}

static void rst_node_gen(xmlNodePtr par, int id, char *addr, char *uri)
{
		if(!par)
				return ;
		char rstid[8];
		snprintf(rstid, 7, "RST%d", id);

		xmlNodePtr rst = xmlNewChild(par, NULL, \
						BAD_CAST "wst:RequestSecurityToken", BAD_CAST NULL);
		xmlNewProp(rst, "Id", rstid);
		xmlNewChild(rst, NULL, BAD_CAST "wst:RequestType", BAD_CAST "http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue");
		xmlNodePtr wsp_AppliesTo = xmlNewChild(rst, NULL, BAD_CAST "wsp:AppliesTo", \
						BAD_CAST NULL);
		xmlNodePtr wsa_EndpointReference = xmlNewChild(wsp_AppliesTo, NULL, BAD_CAST "wsa:EndpointReference", \
						BAD_CAST NULL);
		xmlNewChild(wsa_EndpointReference, NULL, BAD_CAST "wsa:Address", BAD_CAST addr);
		if(uri) {
				xmlNodePtr wsse_PolicyReference = xmlNewChild(rst, NULL, BAD_CAST "wsse:PolicyReference", BAD_CAST NULL
								);
				xmlNewProp(wsse_PolicyReference, "URI", uri);
		}
}

static GString * sso_soap_xml_gen(const char *name, const char *pass)
{
	xmlChar *xml_buf = NULL;
	int xml_len = 0;
    xmlDocPtr doc = NULL;       /* document pointer */
    xmlNodePtr root_node = NULL;/* node pointers */
	xmlNodePtr header, body;

    /* 
     * Creates a new document, a node and set it as a root node
     */
    doc = xmlNewDoc(BAD_CAST "1.0");
    root_node = xmlNewNode(NULL, BAD_CAST "Envelope");
	xmlNewProp(root_node, "xmlns", "http://schemas.xmlsoap.org/soap/envelope/");
	xmlNewProp(root_node, "xmlns:wsse", "http://schemas.xmlsoap.org/ws/2003/06/secext");
	xmlNewProp(root_node, "xmlns:saml", "urn:oasis:names:tc:SAML:1.0:assertion");
	xmlNewProp(root_node, "xmlns:wsp", "http://schemas.xmlsoap.org/ws/2002/12/policy");
	xmlNewProp(root_node, "xmlns:wsu", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd");
	xmlNewProp(root_node, "xmlns:wsa", "http://schemas.xmlsoap.org/ws/2004/03/addressing");
	xmlNewProp(root_node, "xmlns:wssc", "http://schemas.xmlsoap.org/ws/2004/04/sc");
	xmlNewProp(root_node, "xmlns:wst", "http://schemas.xmlsoap.org/ws/2004/04/trust");
    xmlDocSetRootElement(doc, root_node);


	header = xmlNewChild(root_node, NULL, BAD_CAST "Header", BAD_CAST NULL);
	xmlNodePtr ps_AuthInfo = xmlNewChild(header, NULL, BAD_CAST "ps:AuthInfo", BAD_CAST NULL);
	xmlNewProp(ps_AuthInfo, "xmlns:ps", "http://schemas.microsoft.com/Passport/SoapServices/PPCRL");
	xmlNewProp(ps_AuthInfo, "Id", "PPAuthInfo");
	xmlNewChild(ps_AuthInfo, NULL, BAD_CAST "ps:HostingApp", BAD_CAST "{7108E71A-9926-4FCB-BCC9-9A9D3F32E423}");
	xmlNewChild(ps_AuthInfo, NULL, BAD_CAST "ps:BinaryVersion", \
					BAD_CAST "4");
	xmlNewChild(ps_AuthInfo, NULL, BAD_CAST "ps:RequestParams", BAD_CAST "AQAAAAIAAABsYwQAAAAyMDUy");
	xmlNewChild(ps_AuthInfo, NULL, BAD_CAST "ps:Cookies", BAD_CAST NULL);
	xmlNewChild(ps_AuthInfo, NULL, BAD_CAST "ps:UIVersion", BAD_CAST "1");
	xmlNodePtr wsse_Security = xmlNewChild(header, NULL, BAD_CAST "wsse:Security", BAD_CAST NULL);
	xmlNodePtr wsse_UsernameToken = xmlNewChild(wsse_Security, NULL, BAD_CAST "wsse:UsernameToken", \
					BAD_CAST NULL);
	xmlNewProp(wsse_UsernameToken, "Id", "user");
	xmlNewChild(wsse_UsernameToken, NULL, BAD_CAST "wsse:Username", BAD_CAST name);
	xmlNewChild(wsse_UsernameToken, NULL, BAD_CAST "wsse:Password", BAD_CAST pass);

	/* add body node */
	body = xmlNewChild(root_node, NULL, BAD_CAST "Body", BAD_CAST NULL);
	xmlNodePtr ps_RequestMultipleSecurityTokens = xmlNewChild(body, NULL, BAD_CAST "ps:RequestMultipleSecurityTokens", BAD_CAST NULL);
	xmlNewProp(ps_RequestMultipleSecurityTokens, "xmlns:ps", "http://schemas.microsoft.com/Passport/SoapServices/PPCRL");
	xmlNewProp(ps_RequestMultipleSecurityTokens, "Id", "RSTS");
	rst_node_gen(ps_RequestMultipleSecurityTokens, 0, "http://Passport.NET/tb", NULL);
	rst_node_gen(ps_RequestMultipleSecurityTokens, 1, "messengerclear.live.com", "MBI_KEY_OLD");
	rst_node_gen(ps_RequestMultipleSecurityTokens, 2, "messenger.msn.com", "?id=507");
	rst_node_gen(ps_RequestMultipleSecurityTokens, 3, "contacts.msn.com", "MBI");
	rst_node_gen(ps_RequestMultipleSecurityTokens, 4, "messengersecure.live.com", "MBI_SSL");
	rst_node_gen(ps_RequestMultipleSecurityTokens, 5, "spaces.live.com", "MBI");
	rst_node_gen(ps_RequestMultipleSecurityTokens, 6, "storage.msn.com", "MBI");
	
	xmlDocDumpFormatMemoryEnc(doc, &xml_buf, &xml_len, "utf-8", 1);

    /*free the document */
    xmlFreeDoc(doc);
    /*
     *Free the global variables that may
     *have been allocated by the parser.
     */
    xmlCleanupParser();

    /*
     * this is to debug memory for regression tests
     */
    xmlMemoryDump();
	
	GString *bu = g_string_new_len(xml_buf, xml_len);

	debug_log(9, "{%s}\n", bu->str);

    return bu;
}

GString *msn_sso_request_soap_gen(const char *name, const char *pass)
{
	GString *res = NULL;
	GString *xml = NULL;

	xml = sso_soap_xml_gen(name, pass);
	assert(xml);
	res = g_string_new(NULL);
	g_string_printf(res, "POST /RST.srf HTTP/1.1\r\nHost: login.live.com\r\n"\
					"Content-Length: %d\r\n\r\n", xml->len);
	g_string_append_len(res, xml->str, xml->len);
	g_string_free(xml, 1);
	debug_log(9, "SSO REQUEST{%s}\n", res->str);
	return res;
}

GString *msn_membership_get_soap_xml_gen(const char *ticket, const char *last)
{
	xmlChar *xml_buf = NULL;
	int xml_len = 0;
    xmlDocPtr doc = NULL;       /* document pointer */
    xmlNodePtr root_node = NULL;/* node pointers */
	xmlNodePtr header, body;

    /* 
     * Creates a new document, a node and set it as a root node
     */
    doc = xmlNewDoc(BAD_CAST "1.0");
    root_node = xmlNewNode(NULL, BAD_CAST "soap:Envelope");
	xmlNewProp(root_node, "xmlns:soap", "http://schemas.xmlsoap.org/soap/envelope/");
    xmlDocSetRootElement(doc, root_node);

	header = xmlNewChild(root_node, NULL, BAD_CAST "soap:Header", BAD_CAST NULL);
	xmlNewProp(header, "xmlns:soap", "http://schemas.xmlsoap.org/soap/envelope/");
	xmlNodePtr app_header = xmlNewChild(header, NULL, BAD_CAST "ABApplicationHeader", BAD_CAST NULL);
	xmlNewProp(app_header, "xmlns", "http://www.msn.com/webservices/AddressBook");
	xmlNodePtr app_id = xmlNewChild(app_header, NULL, BAD_CAST "ApplicationId", \
					BAD_CAST "09607671-1C32-421F-A6A6-CBFAA51AB5F4");
	xmlNewProp(app_id, "xmlns", "http://www.msn.com/webservices/AddressBook");
	/* add IsMigration */
	xmlNodePtr ismig = xmlNewChild(app_header, NULL, BAD_CAST "IsMigration", \
					BAD_CAST "false");
	xmlNewProp(ismig, "xmlns", "http://www.msn.com/webservices/AddressBook");
	/* add PartnerScenario */
	xmlNodePtr part = xmlNewChild(app_header, NULL, BAD_CAST "PartnerScenario", \
					BAD_CAST "Initial");
	xmlNewProp(part, "xmlns", "http://www.msn.com/webservices/AddressBook");
	/* add soap:Header->ABAuthHeader */
	xmlNodePtr authheader = xmlNewChild(header, NULL, BAD_CAST "ABAuthHeader", \
					BAD_CAST NULL);
	xmlNewProp(authheader, "xmlns", "http://www.msn.com/webservices/AddressBook");
	/* add soap:Header->ABAuthHeader->ManagedGroupRequest */
	xmlNodePtr manag = xmlNewChild(authheader, NULL, BAD_CAST "ManagedGroupRequest", \
					BAD_CAST "false");
	xmlNewProp(manag, "xmlns", "http://www.msn.com/webservices/AddressBook");
	/* add soap:Header->ABAuthHeader->TicketToken */
	xmlNodePtr tic_token = xmlNewChild(authheader, NULL, BAD_CAST "TicketToken", \
					BAD_CAST ticket);

	/* add soap:Body */
	body = xmlNewChild(root_node, NULL, BAD_CAST "soap:Body", BAD_CAST NULL);
	xmlNewProp(body, "xmlns:soap", "http://schemas.xmlsoap.org/soap/envelope/");
	/* add soap:Body->FindMembership */
	xmlNodePtr fms = xmlNewChild(body, NULL, BAD_CAST "FindMembership", BAD_CAST NULL);
	xmlNewProp(fms, "xmlns", "http://www.msn.com/webservices/AddressBook");
	/* add soap:Body->FindMembership->serviceFilter */
	xmlNodePtr sf = xmlNewChild(fms, NULL, BAD_CAST "serviceFilter", BAD_CAST NULL);
	xmlNewProp(sf, "xmlns", "http://www.msn.com/webservices/AddressBook");
	/* add soap:Body->FindMembership->serviceFilter->types */
	xmlNodePtr types = xmlNewChild(sf, NULL, BAD_CAST "Types", BAD_CAST NULL);
	xmlNewProp(types, "xmlns", "http://www.msn.com/webservices/AddressBook");
	/* add soap:Body->FindMembership->serviceFilter->types->ServiceType */
	xmlNodePtr type;
	type = xmlNewChild(types, NULL, BAD_CAST "ServiceType", \
					BAD_CAST "Messenger");
	xmlNewProp(type, "xmlns", "http://www.msn.com/webservices/AddressBook");
	/*
	type = xmlNewChild(types, NULL, BAD_CAST "ServiceType", \
					BAD_CAST "Invitation");
	xmlNewProp(type, "xmlns", "http://www.msn.com/webservices/AddressBook");
	type = xmlNewChild(types, NULL, BAD_CAST "ServiceType", \
					BAD_CAST "SocialNetwork");
	xmlNewProp(type, "xmlns", "http://www.msn.com/webservices/AddressBook");
	type = xmlNewChild(types, NULL, BAD_CAST "ServiceType", \
					BAD_CAST "Space");
	xmlNewProp(type, "xmlns", "http://www.msn.com/webservices/AddressBook");
	type = xmlNewChild(types, NULL, BAD_CAST "ServiceType", \
					BAD_CAST "Profile");
	xmlNewProp(type, "xmlns", "http://www.msn.com/webservices/AddressBook");
	*/
	/*  add soap:Body->FindMembership->View */
	xmlNodePtr view = xmlNewChild(fms, NULL, BAD_CAST "View", BAD_CAST "Full");
	xmlNewProp(view, "xmlns", "http://www.msn.com/webservices/AddressBook");
	/* add soap:Body->FindMembership->soap:Body->deltasOnly */
	xmlNodePtr delt = xmlNewChild(fms, NULL, BAD_CAST "deltasOnly", BAD_CAST "false");
	xmlNewProp(delt, "xmlns", "http://www.msn.com/webservices/AddressBook");
	/* add soap:Body->FindMembership->soap:Body->lastChange */
	xmlNodePtr lastc = xmlNewChild(fms, NULL, BAD_CAST "lastChange", \
					BAD_CAST last);
	xmlNewProp(lastc, "xmlns", "http://www.msn.com/webservices/AddressBook");
	
	xmlDocDumpFormatMemoryEnc(doc, &xml_buf, &xml_len, "utf-8", 1);

    /*free the document */
    xmlFreeDoc(doc);

    /*
     *Free the global variables that may
     *have been allocated by the parser.
     */
    xmlCleanupParser();

    /*
     * this is to debug memory for regression tests
     */
    xmlMemoryDump();
	
	GString *bu = g_string_new_len(xml_buf, xml_len);
    return bu;
}

GString * msn_contact_get_soap_xml_gen(const char *ticket, const char *last)
{
	xmlChar *xml_buf = NULL;
	int xml_len = 0;
    xmlDocPtr doc = NULL;       /* document pointer */
    xmlNodePtr root_node = NULL;/* node pointers */
	xmlNodePtr header, body;

    /* 
     * Creates a new document, a node and set it as a root node
     */
    doc = xmlNewDoc(BAD_CAST "1.0");
    root_node = xmlNewNode(NULL, BAD_CAST "soap:Envelope");
	xmlNewProp(root_node, "xmlns:soap", "http://schemas.xmlsoap.org/soap/envelope/");
    xmlDocSetRootElement(doc, root_node);

	header = xmlNewChild(root_node, NULL, BAD_CAST "soap:Header", BAD_CAST NULL);
	xmlNewProp(header, "xmlns:soap", "http://schemas.xmlsoap.org/soap/envelope/");
	xmlNodePtr app_header = xmlNewChild(header, NULL, BAD_CAST "ABApplicationHeader", BAD_CAST NULL);
	xmlNewProp(app_header, "xmlns", "http://www.msn.com/webservices/AddressBook");
	xmlNodePtr app_id = xmlNewChild(app_header, NULL, BAD_CAST "ApplicationId", \
					BAD_CAST "09607671-1C32-421F-A6A6-CBFAA51AB5F4");
	xmlNewProp(app_id, "xmlns", "http://www.msn.com/webservices/AddressBook");
	/* add IsMigration */
	xmlNodePtr ismig = xmlNewChild(app_header, NULL, BAD_CAST "IsMigration", \
					BAD_CAST "false");
	xmlNewProp(ismig, "xmlns", "http://www.msn.com/webservices/AddressBook");
	/* add PartnerScenario */
	xmlNodePtr part = xmlNewChild(app_header, NULL, BAD_CAST "PartnerScenario", \
					BAD_CAST "Initial");
	xmlNewProp(part, "xmlns", "http://www.msn.com/webservices/AddressBook");
	/* add soap:Header->ABAuthHeader */
	xmlNodePtr authheader = xmlNewChild(header, NULL, BAD_CAST "ABAuthHeader", \
					BAD_CAST NULL);
	xmlNewProp(authheader, "xmlns", "http://www.msn.com/webservices/AddressBook");
	/* add soap:Header->ABAuthHeader->ManagedGroupRequest */
	xmlNodePtr manag = xmlNewChild(authheader, NULL, BAD_CAST "ManagedGroupRequest", \
					BAD_CAST "false");
	xmlNewProp(manag, "xmlns", "http://www.msn.com/webservices/AddressBook");
	/* add soap:Header->ABAuthHeader->TicketToken */
	xmlNodePtr tic_token = xmlNewChild(authheader, NULL, BAD_CAST "TicketToken", \
					BAD_CAST ticket);

	/* add soap:Body */
	body = xmlNewChild(root_node, NULL, BAD_CAST "soap:Body", BAD_CAST NULL);
	xmlNewProp(body, "xmlns", "http://www.msn.com/webservices/AddressBook");
	/* add soap:Body->ABFindAll */
	xmlNodePtr abfindall = xmlNewChild(body, NULL, BAD_CAST "soap:ABFindAll", BAD_CAST NULL);
	xmlNewProp(abfindall, "xmlns", "http://www.msn.com/webservices/AddressBook");
	/* add soap:Body->ABFindAll->abId */
	xmlNodePtr abid = xmlNewChild(abfindall, NULL, BAD_CAST "soap:abId", \
				   	BAD_CAST "00000000-0000-0000-0000-000000000000");
	xmlNewProp(abid, "xmlns", "http://www.msn.com/webservices/AddressBook");
	/* add soap:Body->ABFindAll->abView */
	xmlNodePtr abview = xmlNewChild(abfindall, NULL, BAD_CAST "soap:abView", \
				   	BAD_CAST "Full");
	/* add soap:Body->ABFindAll->deltasOnly */
	xmlNodePtr deltasonly = xmlNewChild(abfindall, NULL, BAD_CAST "soap:deltasOnly", \
				   	BAD_CAST "false");
	/* add soap:Body->ABFindAll->lastChange */
	xmlNodePtr lastchange = xmlNewChild(abfindall, NULL, BAD_CAST "soap:lastChange", \
				   	BAD_CAST last);


	xmlDocDumpFormatMemoryEnc(doc, &xml_buf, &xml_len, "utf-8", 1);
    /*free the document */
    xmlFreeDoc(doc);
    /*
     *Free the global variables that may
     *have been allocated by the parser.
     */
    xmlCleanupParser();
    /*
     * this is to debug memory for regression tests
     */
    xmlMemoryDump();
	GString *bu = g_string_new_len(xml_buf, xml_len);
    return bu;
}

GString *msn_contact_add_soap_xml_gen(const char *ticket, const char *passport, const char *role)
{
	xmlChar *xml_buf = NULL;
	int xml_len = 0;
    xmlDocPtr doc = NULL;       /* document pointer */
    xmlNodePtr root_node = NULL;/* node pointers */
	xmlNodePtr header, body;

    /* 
     * Creates a new document, a node and set it as a root node
     */
    doc = xmlNewDoc(BAD_CAST "1.0");
    root_node = xmlNewNode(NULL, BAD_CAST "soap:Envelope");
	xmlNewProp(root_node, "xmlns:soap", "http://schemas.xmlsoap.org/soap/envelope/");
	xmlNewProp(root_node, "xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
	xmlNewProp(root_node, "xmlns:xsd", "http://www.w3.org/2001/XMLSchema");
	xmlNewProp(root_node, "xmlns:soapenc", "http://schemas.xmlsoap.org/soap/encoding/");
    xmlDocSetRootElement(doc, root_node);

	header = xmlNewChild(root_node, NULL, BAD_CAST "soap:Header", BAD_CAST NULL);
	xmlNodePtr app_header = xmlNewChild(header, NULL, BAD_CAST "ABApplicationHeader", BAD_CAST NULL);
	xmlNewProp(app_header, "xmlns", "http://www.msn.com/webservices/AddressBook");
	xmlNodePtr app_id = xmlNewChild(app_header, NULL, BAD_CAST "ApplicationId", \
					BAD_CAST "09607671-1C32-421F-A6A6-CBFAA51AB5F4");
	xmlNewProp(app_id, "xmlns", "http://www.msn.com/webservices/AddressBook");
	/* add IsMigration */
	xmlNodePtr ismig = xmlNewChild(app_header, NULL, BAD_CAST "IsMigration", \
					BAD_CAST "false");
	xmlNewProp(ismig, "xmlns", "http://www.msn.com/webservices/AddressBook");
	/* add PartnerScenario */
	xmlNodePtr part = xmlNewChild(app_header, NULL, BAD_CAST "PartnerScenario", \
					BAD_CAST "Initial");
	xmlNewProp(part, "xmlns", "http://www.msn.com/webservices/AddressBook");
	/* add soap:Header->ABAuthHeader */
	xmlNodePtr authheader = xmlNewChild(header, NULL, BAD_CAST "ABAuthHeader", \
					BAD_CAST NULL);
	xmlNewProp(authheader, "xmlns", "http://www.msn.com/webservices/AddressBook");
	/* add soap:Header->ABAuthHeader->ManagedGroupRequest */
	xmlNodePtr manag = xmlNewChild(authheader, NULL, BAD_CAST "ManagedGroupRequest", \
					BAD_CAST "false");
	xmlNewProp(manag, "xmlns", "http://www.msn.com/webservices/AddressBook");
	/* add soap:Header->ABAuthHeader->TicketToken */
	xmlNodePtr tic_token = xmlNewChild(authheader, NULL, BAD_CAST "TicketToken", \
					BAD_CAST ticket);

	/* add soap:Body */
	body = xmlNewChild(root_node, NULL, BAD_CAST "soap:Body", BAD_CAST NULL);
	/* soap:Body:AddMember */
	xmlNodePtr addmember = xmlNewChild(body, NULL, "AddMember", NULL);
	xmlNewProp(addmember, "xmlns", "http://www.msn.com/webservices/AddressBook");

	xmlNodePtr serv_handle = xmlNewChild(addmember, NULL, BAD_CAST "serviceHandle", BAD_CAST NULL);
	xmlNewChild(serv_handle, NULL, BAD_CAST "Id", "0");
	xmlNewChild(serv_handle, NULL, "Type", "Messenger");
	xmlNewChild(serv_handle, NULL, "ForeignId", NULL);
	xmlNodePtr memberships = xmlNewChild(addmember, NULL, "memberships", NULL);
	xmlNodePtr membership = xmlNewChild(memberships, NULL, "Membership", NULL);
	/* add soap:Body:memberships:Membership:MemberRole */
	xmlNewChild(membership, NULL, "MemberRole", role);
	/* add ...:Members */
	xmlNodePtr members = xmlNewChild(membership, NULL, "Members", NULL);
	xmlNodePtr member = xmlNewChild(members, NULL, "Member", NULL);
	xmlNewProp(member, "xsi:type", "PassportMember");
	xmlNewProp(member, "xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
	xmlNewChild(member, NULL, "Type", "Passport");
	xmlNewChild(member, NULL, "State", "Accepted");
	xmlNewChild(member, NULL, "PassportName", passport);

	xmlDocDumpFormatMemoryEnc(doc, &xml_buf, &xml_len, "utf-8", 1);
    /*free the document */
    xmlFreeDoc(doc);
    /*
     *Free the global variables that may
     *have been allocated by the parser.
     */
    xmlCleanupParser();
    /*
     * this is to debug memory for regression tests
     */
    xmlMemoryDump();
	GString *bu = g_string_new_len(xml_buf, xml_len);
    return bu;
}
